/*
Adaptors:  brief Definition of function-adaptor classes from thrust to fui.
    Copyright (C) 2012  Jorge E. A. Atala
                        FuDePAN
    This file is part of the Fui Proyect.

    Fui is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Fui is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Fui.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef GENERAL_ADAPTORS_H
#   define GENERAL_ADAPTORS_H
namespace fui
{

struct FirstIndexOTL : public unary_function<unsigned int, unsigned int>
{

    unsigned int _top;

    __host__ __device__
    FirstIndexOTL(unsigned int top)
    {
        _top = top;
    }

    __host__ __device__
    unsigned int operator()(unsigned int index) const
    {
        unsigned int result = 0;
        unsigned int counter = _top;
        unsigned int reduction = _top - 1;
        while (reduction > 0 && index >= counter)
        {
            ++result;
            counter +=  reduction--;
        }

        return result;
    }
};


struct SecondtIndexOTL : public unary_function<unsigned int, unsigned int>
{
    unsigned int _top;

    __host__ __device__
    SecondtIndexOTL(unsigned int top)
    {
        _top = top;
    }

    __host__ __device__
    unsigned int operator()(unsigned int index) const
    {
        unsigned int counter = _top;
        unsigned int reduction = _top - 1;
        while (reduction > 0 && index >= counter)
            counter +=  reduction--;

        return (counter - index) + (_top - reduction - 1);
    }
};

struct FirstIndexOTA : public unary_function<unsigned int, unsigned int>
{

    unsigned int _top;

    __host__ __device__
    FirstIndexOTA(unsigned int top)
    {
        _top = top;
    }

    __host__ __device__
    unsigned int operator()(unsigned int index) const
    {
        return (unsigned int)(index / _top);
    }
};


struct SecondtIndexOTA : public unary_function<unsigned int, unsigned int>
{
    unsigned int _top;

    __host__ __device__
    SecondtIndexOTA(unsigned int top)
    {
        _top = top;
    }

    __host__ __device__
    unsigned int operator()(unsigned int index) const
    {
        return index % _top;
    }
};


template<class Arg, class Result>
struct combinatorial_function
{
    typedef typename permutation_iterator<typename device_vector<Arg>::type::iterator, size_t*>::type Iterator;
    __host__ __device__
    virtual Result operator()(Iterator begin, const Iterator end) = 0;
};

}
#endif
